#include "la.h"
#include "cr.h"
#include "cw.h"
#include <stdlib.h>
#include <stdio.h>

struct sListAsoc
{
	Cinta elems;
	int tam;
};

ListAsoc
la_empty(void)
{
	ListAsoc l;
	l = (ListAsoc) malloc (sizeof(struct sListAsoc));
	if (l!= NULL)
	{
		l->elems = cinta_create(aList_vacia());
		l->tam = 0;
		if (l->elems != NULL)
			cinta_arr(l->elems);
		else
		{
			free(l);
			l = NULL;
			exit(EXIT_FAILURE);
		}	
	}
return l;
}

void
la_add(ListAsoc l, Key k, Data d)
{
	Tuple t;
	if (!la_exists(l,k))
	{	
		t = tuple_fromKeyData(k,d);
		cinta_ins(l->elems,t);
		l->tam += 1;
		t = tuple_destroy(t);
	}
}

Bool
la_exists(ListAsoc l, Key k)
{
	Bool found;
	Key k2;
	Tuple t;
	found = FALSE;
	cinta_arr(l->elems);
	while (!(cinta_fin(l->elems)) && !found)
	{
		t = cinta_elec(l->elems);
		k2 = tuple_fst(t);
		if (key_eq(k,k2))
			found = TRUE;
		else
			cinta_av(l->elems);
		k2 = key_destroy(k2);
		t = tuple_destroy(t);
	}
return found;
}

Data
la_search(ListAsoc l, Key k)
{
	Bool found;
	Key k2;
	Data dt;
	Tuple t;
	found = FALSE;
	
	if (la_exists(l,k))
	{
		cinta_arr(l->elems);
		while (!found)
		{
			t = cinta_elec(l->elems);
			k2 = tuple_fst(t);
			if (key_eq(k,k2))
			{
				found = TRUE;
				dt = tuple_snd(t);
			}
			else
				cinta_av(l->elems);
			k2 = key_destroy(k2);
			t = tuple_destroy(t);
		}
	}
	else
		dt = NULL;
return dt;
}

void
la_del(ListAsoc l, Key k)
{
	Bool found;
	Key k2;
	Tuple t;
	found = FALSE;
	
	if (la_exists(l,k))
	{
		cinta_arr(l->elems);
		while(!found)
		{
			t = cinta_elec(l->elems);
			k2 = tuple_fst(t);
			if (key_eq(k,k2))	
			{
				cinta_del(l->elems);
				found = TRUE;
				l -> tam -=1;
			}
			else
				cinta_av(l->elems);
			k2 = key_destroy(k2);
			t = tuple_destroy(t);
			
		}
	}
}

int
la_length(ListAsoc l)
{
return (l->tam);
}

void
print_la(ListAsoc l)
{
	Key k;
	Data d;
	Tuple t;
	char * s2;
	char * s1;
	cinta_arr(l->elems);
	while (!(cinta_fin(l->elems)))
	{
		s1 = (char *) calloc (key_maxLen(),sizeof(char));
		if (s1 != NULL)
		{
			t = cinta_elec(l->elems);
			k = tuple_fst(t);
			d = tuple_snd(t);
			key_toString(k,s1);
			s2 = data_toString(d);
			printf("%s: %s\n",s1,s2);
			k = key_destroy(k);
			d = data_destroy(d);
			t = tuple_destroy(t);
			free(s2);
			free(s1);
			s2 = NULL;
			s1 = NULL;
		}
		cinta_av(l->elems);
	}	
}

ListAsoc
la_destroy(ListAsoc l)
{
	aList aux;
	if (l!= NULL)
	{
		aux = cinta_destroy(l->elems);
		aux = aList_destroy(aux);
		free(l);
		l = NULL;
	}

return l;
}

ListAsoc
la_fromFile(char * nomfile)
{
	ListAsoc l;
	cr c1;
	Tuple t;
	Key k;
	Data d;
	
	c1 = cr_create(nomfile);
	l = la_empty();
	
	/*if (c1 == NULL)
		//exit(EXIT_FAILURE);
		*/
	if(c1!=NULL)
	{
	cr_arr(c1);
	
	while (!(cr_fin(c1)))
	{
		t = cr_elec(c1);
		k = tuple_fst(t);
		d = tuple_snd(t);
		la_add(l,k,d);
		cr_av(c1);
		t = tuple_destroy(t);
	}
	
	c1 = cr_destroy(c1);
	}
		
return l;
}

void
la_toFile(char * nomfile, ListAsoc l)
{
	cw c1;
	Tuple t;
	
	c1 = cw_create(nomfile);
	cw_arr(c1);
	cinta_arr(l->elems);
	
	while (!(cinta_fin(l->elems)))
	{
		t = cinta_elec(l->elems);
		cw_ins(c1,t);
		cinta_av(l->elems);
		t = tuple_destroy(t);
	}
	
	c1 = cw_destroy(c1);
}
